import axios from 'axios';
import store from '@/store';
import qs from 'qs';
import router from '@/router';
import { message } from 'ant-design-vue';
import { Result } from '@/model/common';

// 响应头中token的参数配置
const PARAM_TOKEN_KEY = 'authorization';
const PARAM_TOKEN_PREFIX = 'Bearer ';

// 需要重新登录的状态码
const needLoginResponseCodes = [110311];
// 登录是否过期
let loginExpired = false;

const config = {
    baseURL: import.meta.env.VITE_APP_BASE_URL as string,
    withCredentials: true,
    timeout: 30000,
};

const instance = axios.create(config);

/**
 * http request 拦截器
 */
instance.interceptors.request.use(
    (requestConfig) => {
        if (store.state.token && requestConfig.headers) {
            requestConfig.headers[PARAM_TOKEN_KEY] = `${PARAM_TOKEN_PREFIX}${store.state.token}`;
            requestConfig.headers['Content-Type'] = 'application/json;charset=UTF-8';
        }
        if (requestConfig.method === 'get') {
            requestConfig.paramsSerializer = (params) => {
                return qs.stringify(params, { arrayFormat: 'repeat' });
            };
        }
        return requestConfig;
    },
    (error) => {
        return Promise.reject(error);
    }
);

/**
 * http response 拦截器
 */
instance.interceptors.response.use(
    (response) => {
        const token = response.headers[PARAM_TOKEN_KEY];
        if (token) {
            store.commit('token', token);
            document.cookie = 'token=' + token;
        }
        if (0 === response.data.code) {
            loginExpired = false;
            return Promise.resolve(response.data);
        }
        // 判断是否需要重新登录
        if (needLoginResponseCodes.indexOf(response.data.code) >= 0) {
            // 重新登录只提示一次，不重复提示
            if (loginExpired) {
                return Promise.reject(response.data);
            }
            loginExpired = true;
            // 清除缓存，跳转到登录页面
            message.error('登录信息已失效，请重新登录');
            router.push('/login');
        }
        return Promise.reject(response.data);
    },
    (error) => {
        const err = new Result();
        if (error && error.message) {
            if (/timeout of .* exceeded/.test(error.message)) {
                err.msg = '请求超时，请重试';
            } else {
                switch (error.message) {
                    case 'Network Error':
                        err.msg = '网络异常';
                        break;
                    default:
                        err.msg = error.message;
                        break;
                }
            }
        }
        return Promise.reject(err);
    }
);

export default class Http {
    public static get(url: string, params?: any): Promise<Result> {
        const requestConfig = {
            method: 'GET',
            url,
            params,
        };
        return this.request(requestConfig);
    }

    public static post(url: string, data?: any): Promise<Result> {
        const requestConfig = {
            method: 'POST',
            url,
            data,
        };
        return this.request(requestConfig);
    }

    public static request(requestConfig: any): Promise<Result> {
        return new Promise((resolve, reject) => {
            instance
                .request(requestConfig)
                .then((res: any) => {
                    resolve(res);
                })
                .catch((err) => {
                    reject(err);
                });
        });
    }

    public static all(requestList: Array<Promise<Result>>) {
        return new Promise((resolve, reject) => {
            axios
                .all(requestList)
                .then(
                    axios.spread((...args) => {
                        const res = [] as any;
                        console.log(`all-args - ${JSON.stringify(args)}`);
                        args.forEach((value: any) => {
                            res.push(value.data);
                        });
                        resolve(res);
                    })
                )
                .catch((err) => {
                    console.log(`all-err - ${JSON.stringify(err)}`);
                    reject(err);
                });
        });
    }
}
